AclPermissionDetail = function() {

	var aclConfigEntryData = [];
	var entitys = {};
	var _this = this;

	AclPermissionService.loadAclConfigEntrys(function(result){

		Ext.each(result, function(r){
			var name = r.propertyName;
			var index = name.lastIndexOf('.');
			var entityName = name.substring(0, index);
			var propertyName = name.substring(index + 1);

			if(entitys[entityName] === undefined) {
				entitys[entityName] = [];
				aclConfigEntryData.push([entityName]);
			}
			entitys[entityName].push([propertyName, propertyName]);
		});
	});

	var LOGICNODE_AND = 0, LOGICNODE_OR = 1;
	var LOGICNODE_TEXT = [i18n.global.and, i18n.global.or];

	var dsEntity = new Ext.data.SimpleStore({
		data: [],
		fields: ['entityName']
    });

    var dsCrudType = new Ext.data.SimpleStore({
    	data: [[0, system.AclPermission.read], [1, system.AclPermission.create], [2, system.AclPermission.update], [3, i18n.global.del]],
		fields: ['crudType', 'display']
    });

    var dsProperty = new Ext.data.SimpleStore({
    	data: [],
		fields: ['propertyName', 'display']
    });

	var dsOperator = new Ext.data.SimpleStore({
    	data: [[1, system.AclPermission.equal], [2, system.AclPermission.than], [3, system.AclPermission.thanOrEqual],
    		[4, system.AclPermission.less], [5, system.AclPermission.lessOrEqual], [6, system.AclPermission.among], 
    		[7, system.AclPermission.notEqual], [8, system.AclPermission.contains], [20, system.AclPermission.notContains]
    	],
		fields: ['operator', 'display']
    });

	var formAclPermission = new Ext.FormPanel({
		border: true,
		style: 'margin: 5px 5px',
		bodyStyle: 'padding: 8px 5px 5px',
        items :[{
        	layout:'column',
        	border: false,
        	defaults : {
        		border: false,
        		labelWidth: 65,
        		layout: 'form',
        		columnWidth: 0.5
        	},
            items:[{
                items: [{
                	id: 'comboEntity',
                	xtype: 'combo', 
                	tabIndex: 1,
                	allowBlank: false,
	                fieldLabel: system.AclPermission.entityName,
                    name: 'entityName', 
                    store : dsEntity,
                    displayField: 'entityName',
			        typeAhead : true,
			        mode : 'local',
			        triggerAction : 'all',
			        selectOnFocus : true,
		        	forceSelection : true
                }]
        	}, {
                items: [{
                	id: 'comboCrudType',
                	xtype: 'combo', 
                	tabIndex: 2,
                	allowBlank: false,
	                fieldLabel: system.AclPermission.crudType,
                    name: 'crudType', 
                    store : dsCrudType,
                    valueField: 'crudType',
                    displayField: 'display',
			        typeAhead : true,
			        mode : 'local',
			        triggerAction : 'all',
			        selectOnFocus : true,
		        	forceSelection : true
                }]
            }]
        }]
	});

	var rootAclCondition = new Ext.tree.TreeNode();
	//TODO 树的D&D,isLeaf
	var treeAclCondition = new Ext.tree.TreePanel({
		border: true,
		height: 250,
		bodyStyle: 'margin: 0px 5px',
		autoScroll: true, 
		animate : false,
		root: rootAclCondition,
		buttonAlign: 'left',
    	buttons: [
    		{id: 'btnLogicAnd', text: i18n.global.and, handler: function(){
    			var node = new Ext.tree.TreeNode();
    			node.setText(i18n.global.and);
				node.logicNode = LOGICNODE_AND;
    			appendNode(node);
    		}}, 
    		{id: 'btnLogicOr', text: i18n.global.or, handler: function(){
    			var node = new Ext.tree.TreeNode();
    			node.setText(i18n.global.or);
				node.logicNode = LOGICNODE_OR;
    			appendNode(node);
    		}}, 
    		{id: 'btnLogicToggle', text: i18n.global.and + '<->' + i18n.global.or, handler: function(){
    			var node = treeAclCondition.selModel.selNode;
    			if(node == null)
    			{
    				return;
    			}
    				
    			node.setText(node.text.toggle(i18n.global.and, i18n.global.or));
    			node.logicNode = node.logicNode === LOGICNODE_AND ? LOGICNODE_OR : LOGICNODE_AND;
    		}}, 
    		{id: 'btnConditionAdd', text: system.AclPermission.add, handler: function(){
    			if (!formAclCondition.form.isValid()) return;

    			var v = formAclCondition.form.getValues();
    			var node = new Ext.tree.TreeNode();
    			node.setText(v.propertyName + ' ' + v.operator + ' ' + v.value);
    			node.condition = {
    				propertyName: comboProperty.getValue(), 
    				operator: comboOperator.getValue(), 
    				value: txtValue.getValue()
    			};
    			appendNode(node);
				formAclCondition.form.reset();
    		}}, 
    		{id: 'btnConditionEdit', text: system.AclPermission.edit, disabled: true, handler: function(){
    			if (!formAclCondition.form.isValid()) return;

    			var v = formAclCondition.form.getValues();
    			var node = treeAclCondition.selModel.selNode;
    			if (!node) return;

    			node.setText(v.propertyName + ' ' + v.operator + ' ' + v.value);
    			node.condition = {
    				propertyName: comboProperty.getValue(), 
    				operator: comboOperator.getValue(), 
    				value: txtValue.getValue()
    			};
    		}}, 
    		{text: i18n.global.del, handler: function(){
    			//没有选择节点或者选中的是根节点, 退出此方法
    			var node = treeAclCondition.selModel.selNode;
    			if (!node) return;

    			if (node.isRoot) {
    				while(node.hasChildNodes()) {
					    node.removeChild(node.firstChild);
					}
    			} else {
    				node.remove();
    			}

				formAclCondition.form.reset();
    		}}
    	]
	});

	treeAclCondition.on('click', function(node){
		if (node.logicNode !== undefined) {
			Ext.getCmp('btnLogicAnd').enable();
			Ext.getCmp('btnLogicOr').enable();
			Ext.getCmp('btnLogicToggle').enable();
			Ext.getCmp('btnConditionAdd').enable();
			Ext.getCmp('btnConditionEdit').disable();
		} else {
			Ext.getCmp('btnLogicAnd').disable();
			Ext.getCmp('btnLogicOr').disable();
			Ext.getCmp('btnLogicToggle').disable();
			Ext.getCmp('btnConditionAdd').disable();
			Ext.getCmp('btnConditionEdit').enable();

			formAclCondition.form.setValues(node.condition);
		}
	});

	var formAclCondition = new Ext.FormPanel({
		border: true,
		style: 'margin: 0px 5px',
		bodyStyle: 'padding: 5px 5px 3px',
    	layout:'column',
    	defaults: {
    		columnWidth: 0.33,
    		layout: 'form',
    		border: false,
    		defaultType: 'textfield',
    		labelWidth : 65,
    		defaults: {width: 150, anchor : '-5', allowBlank: false}
		},
        items:[{
            items: [{
            	xtype: 'combo',
            	id: 'comboProperty',
            	tabIndex: 3,
                fieldLabel: system.AclCondition.propertyName,
                name: 'propertyName',
                store : dsProperty,
                valueField: 'propertyName',
                displayField: 'display',
		        typeAhead : true,
		        mode : 'local',
		        triggerAction : 'all',
		        listWidth : 120,
		        selectOnFocus : true,
		        forceSelection : true
            }]
    	}, {
            items: [{
            	xtype: 'combo',
            	id: 'comboOperator',
            	tabIndex: 4,
                fieldLabel: system.AclCondition.operator,
                name: 'operator',
                store : dsOperator,
                valueField: 'operator',
                displayField: 'display',
		        typeAhead : true,
		        mode : 'local',
		        triggerAction : 'all',
		        selectOnFocus : true,
		        forceSelection : true
            }]
    	}, {
            items: [{
                fieldLabel: system.AclCondition.value,
                id: 'txtValue',
                tabIndex: 5,
                name: 'value'
            }]
        }]
	});
	
	this.window = new Ext.Window({
		title: system.AclPermission.permissionDetail,
        width: 550,
        height: 410,
        closeAction: 'hide',
        modal: true, plain: true,
        resizable: false,
        items: [
        	formAclPermission, treeAclCondition, formAclCondition
        ],
        buttons: [
        	{text: i18n.global.save, handler: function(){saveAclPermission();}},
        	{text: i18n.global.cancel, handler: function(){cancelAclPermission();}}
        ]
	});

	var comboEntity = Ext.getCmp('comboEntity');
	var comboCrudType = Ext.getCmp('comboCrudType');
	var comboProperty = Ext.getCmp('comboProperty');
	var comboOperator = Ext.getCmp('comboOperator');
	var txtValue = Ext.getCmp('txtValue');

	comboEntity.on('select', function(combo, record, index){
		treeAclCondition.enable();
		dsProperty.loadData(entitys[record.data.entityName]);
	});

	var appendNode = function(node) {
		var parentNode;
		if (treeAclCondition.selModel.selNode) {
			parentNode = treeAclCondition.selModel.selNode;
		} else {
			parentNode = rootAclCondition;
		}

		parentNode.expand();
		parentNode.appendChild(node);
	};

	var getAclConditions = function(nodeLogic) {
		var aclConditions = [];
		var nodes = [];

		if (nodeLogic.childNodes == undefined) return;

		Ext.each(nodeLogic, function(pnode){
			var aclParentCondition = {};
			if (pnode.logicNode !== undefined) {
				aclParentCondition = {
					logicNode: pnode.logicNode,
					childConditions: []
				};
				nodes.push(aclParentCondition);
			}

			Ext.each(pnode.childNodes, function(node){
				if (node.logicNode !== undefined) {
					aclParentCondition.childConditions = aclParentCondition.childConditions.concat(getAclConditions(node));
				} else {
					var aclCondition = {
						propertyName: node.condition.propertyName,
						operator: node.condition.operator,
						value: node.condition.value,
						logicNode: node.parentNode.logicNode,
						childConditions: []
					};
					aclParentCondition.childConditions.push(aclCondition);
				}
			});
			if (aclParentCondition.childConditions.length > 0) {
				aclConditions.push(aclParentCondition);
			}
		});

		return aclConditions;
	};

	var saveAclPermission = function(){
		if (!formAclPermission.form.isValid()) return;

		var aclPermission = _this.recAclPermission.data;
		aclPermission.entityName = comboEntity.getValue();
		aclPermission.crudType = comboCrudType.getValue();
		aclPermission.aclConditions = getAclConditions(rootAclCondition);

		if (aclPermission.aclConditions.length <= 0) {
			Ext.Msg.alert(i18n.global.save, system.AclPermission.permissionErrorMessage);
			return;
		}

		AclPermissionService.saveOrUpdateAclPermission(aclPermission, function(result){
			Ext.apply(aclPermission, result);
			_this.recAclPermission.commit();
			Ext.Msg.alert(i18n.global.save, i18n.message.saveSucceed, function(){_this.window.hide();});
		});
	};

	var cancelAclPermission = function(){
		if(_this.recAclPermission&&_this.recAclPermission.data.rowStatus===Gfa.GlobalConstant.ROWSTATUS_ADDED){
			_this.recAclPermission.store.remove(_this.recAclPermission);
		}
		_this.window.hide();
	};

	var resetTreeAclCondition = function(aclConditions) {
		var root = treeAclCondition.getRootNode();
		root.setText(i18n.global.and);
		root.logicNode = LOGICNODE_AND;

		while(root.hasChildNodes()) {
			root.removeChild(root.firstChild);
		}

		if (aclConditions.length <= 0) return;

		Ext.each(aclConditions, function(aclCondition){
			if (aclCondition.parentCondition) return;

			root.setText(LOGICNODE_TEXT[aclCondition.logicNode]);
			root.logicNode = aclCondition.logicNode;

			addConditionNodes(aclCondition.childConditions, root);
		});
	};

	var addConditionNodes = function(childConditions, parentNode) {
		if (childConditions == undefined) return;
		//用来保存逻辑'与','或'的树节点 logicNodes[0]为'与', [1]为'或'
		var logicNodes = [];

		Ext.each(childConditions, function(childCondition){
			formAclCondition.form.setValues(childCondition);
			var v = formAclCondition.form.getValues();

			if (Ext.isEmpty(v.propertyName) && Ext.isEmpty(v.operator) && Ext.isEmpty(v.value)) {
				var logicNode = new Ext.tree.TreeNode();
				logicNode.setText(LOGICNODE_TEXT[childCondition.logicNode]);
				logicNode.logicNode = childCondition.logicNode;
				parentNode.appendChild(logicNode);
				logicNodes[childCondition.logicNode] = logicNode;
			} else {
				var conditionNode = new Ext.tree.TreeNode();
				conditionNode.setText(v.propertyName + ' ' + v.operator + ' ' + v.value)
				conditionNode.condition = childCondition;
				parentNode.appendChild(conditionNode);
			}

			if (childCondition.childConditions.length > 0) {
				addConditionNodes(childCondition.childConditions,
							logicNodes[childCondition.logicNode]);
			}
		});
	};

	this.initData = function(data) {

		dsEntity.loadData(aclConfigEntryData);
		if (data.entityName) {
			dsProperty.loadData(entitys[data.entityName]);
		}

		formAclPermission.form.setValues({
			entityName: data.entityName, 
			crudType: data.crudType
		});

		resetTreeAclCondition(data.aclConditions);
		rootAclCondition.expand(true);
		formAclCondition.form.reset();
	};
};

AclPermissionDetail.prototype = {
	show : function(recAclPermission) {
		this.recAclPermission = recAclPermission;
		this.initData(recAclPermission.data);
		var left = Ext.getBody().getWidth()/2 - this.window.getSize().width/2;
		var top = Ext.getBody().getHeight()/2 - this.window.getSize().height/2;
		this.window.setPosition(left, top);
		this.window.show();
	}
};

Ext.onReady(function(){ 

	Ext.form.Field.prototype.msgTarget = 'qtip';

	var rootRole = new Ext.tree.AsyncTreeNode();

	AclPermissionService.loadAllRoleAndAclPermission(function(roles){
		Ext.each(roles, function(role){
			var node = new Ext.tree.TreeNode({id: role.roleId, text: role.roleName});
			node.gfaData = role;
			rootRole.appendChild(node);
		});
	});

	var dsAclPermission = new Gfa.data.Store( {
    	proxy: new Gfa.data.DwrProxy(CommonService),
        reader: new Gfa.data.DwrReader({}, 
        	Ext.data.Record.create(['role', 'entityName', 'crudType']))
	});

	var crudTypeConstans = {0:system.AclPermission.read, 1:system.AclPermission.create, 2:system.AclPermission.update, 3:i18n.global.del};
	var crudTypeRenderer = function(value){
		return crudTypeConstans[value];
	};

	var cmAclPermission = new Ext.grid.ColumnModel([ 
		{header : system.AclPermission.entityName, dataIndex : 'entityName', width: 150}, 
		{header : system.AclPermission.crudType, dataIndex : 'crudType', renderer: crudTypeRenderer}
	]);
	cmAclPermission.defaultSortable = true;

	var pnlAclPermission = new Ext.Panel({
		layout: 'column',
		items: [{
			id: 'treeRolePermission',
			region : 'west',
			xtype: 'treepanel',
			margins : '5 5 5 5',
			width: 250, autoScroll: true,
			animate: false, border: true,
			rootVisible: false, line: false,
			root: rootRole
		}, {
			id: 'gridAclPermission',
			region: 'center',
			margins : '5 5 5 0',
			xtype: 'grid',
			height : 400,
			ds : dsAclPermission,
			cm : cmAclPermission,
			sm : new Ext.grid.RowSelectionModel({singleSelect:true}),
			border: true, loadMask: true,		
			autoScroll : true, disabled: true,
			bbar: [ 
				{text: i18n.global.add, iconCls: 'toolbar-add', handler: addAclPermission},
				{text: i18n.global.edit, iconCls: 'toolbar-edit', handler: editAclPermission},
				{text: i18n.global.del, iconCls: 'toolbar-del', handler: delAclPermission},
				{text: i18n.global.copy, iconCls: 'copy', handler: copyAclPermission}
			]
		}]
	});

	var aclPermissionDetail = new AclPermissionDetail();

	//var cTab = Ext.getCmp(Gfa.GlobalVariable.contentAreaId).activeTab;

	//cTab.add(pnlAclPermission);
	//cTab.doLayout();
	//aclPermissionDetail.window.render(cTab.el);
	pnlAclPermission.render(Ext.getBody());
	aclPermissionDetail.window.render("aclPermissionManagerDiv");
	
	var treeRolePermission = Ext.getCmp('treeRolePermission');
	var gridAclPermission = Ext.getCmp('gridAclPermission');

	treeRolePermission.on('click', function(node){
		if (gridAclPermission.disabled) gridAclPermission.enable();
		dsAclPermission.loadData(node.gfaData.aclPermissions);
	});

	dsAclPermission.on('update', function(ds, rec, op){
		if (op === Ext.data.Record.COMMIT) {
			var aclPermissions = getRole().aclPermissions;
			if (aclPermissions.indexOf(rec.data) === -1) {
				aclPermissions.push(rec.data);
			}
		}
	});

	gridAclPermission.on('rowdblclick', editAclPermission);

	function getRole() {
		return treeRolePermission.selModel.selNode.gfaData;
	}

	function addAclPermission() {
		var record = dsAclPermission.insertNewRecord();
		record.data = {
			role : getRole(),
			rowStatus : Gfa.GlobalConstant.ROWSTATUS_ADDED,
			aclConditions : []
		};
		aclPermissionDetail.show(record);
	}

	function editAclPermission() {
		var selRec = gridAclPermission.getSelections()[0];
		if (!selRec) return;

		selRec.data.rowStatus = Gfa.GlobalConstant.ROWSTATUS_MODIFIED;
		aclPermissionDetail.show(selRec);
	}

	function delAclPermission() {
		var selRec = gridAclPermission.getSelections()[0];
		if (!selRec) return;

		if (selRec.data.rowStatus === Gfa.GlobalConstant.ROWSTATUS_ADDED) {
			dsAclPermission.remove(selRec);
			return;
		}

		selRec.data.rowStatus = Gfa.GlobalConstant.ROWSTATUS_DELETED;
		Ext.Msg.confirm(i18n.message.prompt, i18n.message.confirmDel,
			function(btn, text) {
			if (btn === 'yes') {
				AclPermissionService.saveOrUpdateAclPermission(selRec.data, function(){
					Ext.Msg.alert(i18n.global.del, i18n.message.deleteSucceed);
					dsAclPermission.remove(selRec);
					getRole().aclPermissions.remove(selRec.data);
				});
			}});
	}

	function copyAclPermission() {
		if(!winCopyAclPermission) initWinCopyAclPermission();
		else winCopyAclPermission.show();
        
	}

	var winCopyAclPermission;
	function initWinCopyAclPermission() {
		var root = new Ext.tree.AsyncTreeNode();

		var saveFn = function() {
			var tree = Ext.getCmp('treeCopyAclPermission');
			var sourceNodeId = tree.selModel.selNode.id;
			var targetNode = treeRolePermission.selModel.selNode;
			if (targetNode.id === sourceNodeId) {
				Ext.Msg.alert(i18n.message.prompt,system.AclPermission.copyErrorMessage);
				return;
			}

			AclPermissionService.txRequiredCopyRolePermission(targetNode.id, sourceNodeId, function(result){
				targetNode.gfaData = result;
				winCopyAclPermission.hide();
				dsAclPermission.loadData(result.aclPermissions);
			});
		};

		winCopyAclPermission = new Ext.Window({
        	title: system.AclPermission.copyPermission,
            width: 200,
            height: 250,
            layout: 'fit',
            closeAction: 'hide',
            modal: true,
            items: new Ext.tree.TreePanel({
            	id: 'treeCopyAclPermission',
                border: true,
                lines: false,
                autoScroll : true,
                rootVisible: false,
                root: root,
                listeners: {'dblclick' : saveFn}
            }),
            buttons: [
            	{text: i18n.global.ok, handler: saveFn},
            	{text: i18n.global.cancel, handler: function(){winCopyAclPermission.hide();}}
            ]
        });
        winCopyAclPermission.show();

        Ext.each(rootRole.childNodes, function(node){
			root.appendChild(new Ext.tree.TreeNode({id: node.id, text: node.text}));
		});
	}

});
